#ifndef __M_HOST_H__
#define __M_HOST_H__
#include "exchange.hpp"
#include "queue.hpp"
#include "binding.hpp"
#include "message.hpp"

class VirtualHost{
public:
    using ptr = std::shared_ptr<VirtualHost>;
    VirtualHost(const std::string &hname, const std::string &basedir, const std::string &dbfile):
        _hostname(hname),
        _emp(std::make_shared<ExchangeManager>(dbfile)),
        _mqmp(std::make_shared<MsgQueueManager>(dbfile)),
        _bmp(std::make_shared<BindingManager>(dbfile)),
        _mmp(std::make_shared<MessageManager>(basedir)){

        //系统重启时构造虚拟机对象，所以需要恢复历史消息
        //exchange、queue、binding构造里都会从数据库里恢复
        //message需要通过队列名称恢复，所以手动调用一下
        QueueMap qm = _mqmp->allQueues();
        for (auto &q : qm){
            _mmp->initQueueMessage(q.first);
        }
    }
    bool declareExchange(const std::string &name,
                        mymq::ExchangeType type, bool durable, bool auto_delete,
                        const google::protobuf::Map<std::string, std::string> &args){
        return _emp->declareExchange(name, type, durable, auto_delete, args);
    }

    void deleteExchange(const std::string &name){
        //删除交换机的时候，需要将交换机相关的绑定信息也删除掉
        _bmp->removeExchangeBindings(name);
        return _emp->deleteExchange(name);
    }
    
    bool existsExchange(const std::string &name){
        return _emp->exists(name);
    } 

    Exchange::ptr selectExchange(const std::string &ename){
        return _emp->selectExchange(ename);
    }
    bool declareQueue(const std::string &qname,
                    bool qdurable, bool qexclusive,
                    bool qauto_delete,
                    const google::protobuf::Map<std::string, std::string> &qargs){
        //初始化队列的消息句柄（消息的存储管理）
        _mmp->initQueueMessage(qname);
        //队列的创建
        return _mqmp->declareQueue(qname, qdurable, qexclusive, qauto_delete, qargs);
    }

    void deleteQueue(const std::string &name){
        //删除的时候队列的相关数据有两个：队列的消息，队列的绑定消息
        _mmp->destroyQueueMessage(name);
        _bmp->removeMsgQueueBindings(name);
        return _mqmp->deleteQueue(name);
    }

    bool existsQueue(const std::string &name){
        return _mqmp->exists(name);
    }

    QueueMap allQueues(){
        return _mqmp->allQueues();
    }

    bool bind(const std::string &ename, const std::string &qname, const std::string &key){
        Exchange::ptr ep = _emp->selectExchange(ename);//同时也获取持久化情况
        if (ep.get() == nullptr){
            DLOG("绑定失败：交换机%s不存在！", ename.c_str());
            return false;
        }
        MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
        if (mqp.get() == nullptr){
            DLOG("绑定失败：队列%s不存在！", qname.c_str());
            return false;
        }
        return _bmp->Bind(ename, qname, key, ep->durable && mqp->durable);
    }

    void unbind(const std::string &ename, const std::string &qname){
        return _bmp->unBind(ename, qname);
    }

    MsgQueueBindingMap exchangeBindings(const std::string &ename){
        return _bmp->getExchangeBindings(ename);
    }

    bool existsBinding(const std::string &ename, const std::string &qname){
        return _bmp->exists(ename, qname);
    }

    bool basicPublish(const std::string &qname, mymq::BasicProperties *bp, const std::string &body){
        MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
        if (mqp.get() == nullptr){
            DLOG("发布消息失败：队列%s不存在！", qname.c_str());
            return false;
        }
        return _mmp->insert(qname, bp, body, mqp->durable);
    }

    mqMessagePtr basicConsume(const std::string &qname){
        return _mmp->front(qname);
    }

    void basicAck(const std::string &qname, const std::string &msgid){
        return _mmp->ack(qname, msgid);
    }

    void clear(){
        _emp->clear();
        _mqmp->clear();
        _bmp->clear();
        _mmp->clear();
    }
private:
    std::string _hostname;
    ExchangeManager::ptr _emp;
    MsgQueueManager::ptr _mqmp;
    BindingManager::ptr _bmp;
    MessageManager::ptr _mmp;
};
#endif